import { useCallback, useRef, useEffect } from "react";

// 定义函数类型（支持泛型参数）
type ThrottleFn<T extends any[]> = (...args: T) => void;

// 配置项类型
interface ThrottleOptions {
  leading?: boolean; // 是否立即执行首次调用
  trailing?: boolean; // 是否在时间间隔结束后执行最后一次调用
}

export default <T extends any[]>(
  fn: (...args: T) => void,
  wait = 200,
  options: ThrottleOptions = { leading: true, trailing: true }
): ThrottleFn<T> => {
  const { leading, trailing } = options;
  const timerRef = useRef<NodeJS.Timeout | null>(null);
  const lastExecTimeRef = useRef<number>(0);
  const pendingArgsRef = useRef<T | null>(null);

  // 清理定时器
  const cleanup = () => {
    if (timerRef.current) {
      clearTimeout(timerRef.current);
      timerRef.current = null;
    }
  };

  // 执行函数并更新最后执行时间
  const execute = (...args: T) => {
    lastExecTimeRef.current = Date.now();
    fn(...args);
  };

  // 节流函数主体
  const throttledFn = useCallback(
    (...args: T) => {
      const now = Date.now();
      const timeSinceLastExec = now - lastExecTimeRef.current;

      // 若未到时间间隔，记录参数并设置定时器
      if (timeSinceLastExec < wait) {
        pendingArgsRef.current = args;
        if (trailing && !timerRef.current) {
          timerRef.current = setTimeout(() => {
            if (pendingArgsRef.current) {
              execute(...pendingArgsRef.current);
              pendingArgsRef.current = null;
            }
            cleanup();
          }, wait - timeSinceLastExec);
        }
      } else {
        // 立即执行或重置时间
        if (leading) {
          execute(...args);
        } else {
          lastExecTimeRef.current = now;
        }
      }
    },
    [fn, wait, leading, trailing]
  );

  // 组件卸载时清理定时器
  useEffect(() => cleanup, []);

  return throttledFn;
};
